﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using NthDownload.BL.Persistence;
using NthDownload.Common.Plugins;
using NthDownload.Common.ViewModels;
using NthDownload.Composition;
using NthDownload.Contracts;
using System.Windows.Threading;
using NthDownload.Contracts.Plugins.Downloads;
using System.Collections.Generic;
using System.Linq;

namespace NthDownload.ViewModels
{
    public class MainViewModel : ViewModelConductorBase
    {
        #region Class Members

        private IViewModel _profileViewModel;
        private IViewModel _bandwidthProvidersViewModel;

        private DispatcherTimer _persistenceTimer;

        private ObservableCollection<IDownloadPlugin> _downloadPlugins;

        private bool _isSettingsVisible;

        #endregion Class Members

        #region Constructor

        public MainViewModel()
        {
            //
            // Initialize view models
            //
            ProfileViewModel = new QueuesViewModel();
            BandwidthProvidersViewModel = new BandwidthProvidersViewModel();

            //
            // Show the downloads view
            //
            ShowDownloads();

            //
            // Setup persistence
            //
            SetupPersistenceTimer();
        }

        #endregion Constructor

        #region Properties

        /// <summary>
        /// The profile persistence service
        /// </summary>
        [Import(AllowRecomposition = true)]
        public NthProfilePersistenceService ProfilePersistenceService { get; set; }

        /// <summary>
        /// The available download plugins
        /// </summary>
        [ImportMany(typeof(IDownloadPlugin), AllowRecomposition = true)]
        public ObservableCollection<IDownloadPlugin> DownloadPlugins
        {
            get
            {
                return _downloadPlugins;
            }
            set
            {
                _downloadPlugins = value;
                NotifyOfPropertyChange(() => DownloadPlugins);
                NotifyOfPropertyChange(() => DownloadPluginsWithSettings);
            }
        }

        /// <summary>
        /// The available download plugins
        /// </summary>
        public List<IDownloadPlugin> DownloadPluginsWithSettings
        {
            get
            {
                return new List<IDownloadPlugin>(DownloadPlugins.Where(p => p.HasSettings));
            }
        }

        /// <summary>
        /// Indicates if ther settings menu is visible
        /// </summary>
        public bool IsSettingsVisible
        {
            get
            {
                return _isSettingsVisible;
            }
            private set
            {
                _isSettingsVisible = value;
                NotifyOfPropertyChange(() => IsSettingsVisible);
            }
        }

        #endregion Properties

        #region Private Properties

        /// <summary>
        /// The current profile view model
        /// </summary>
        private IViewModel ProfileViewModel
        {
            get
            {
                return _profileViewModel;
            }
            set
            {
                _profileViewModel = value;
                NotifyOfPropertyChange(() => ProfileViewModel);
            }
        }

        /// <summary>
        /// The current bandwidth providers view model
        /// </summary>
        private IViewModel BandwidthProvidersViewModel
        {
            get
            {
                return _bandwidthProvidersViewModel;
            }
            set
            {
                _bandwidthProvidersViewModel = value;
                NotifyOfPropertyChange(() => BandwidthProvidersViewModel);
            }
        }

        /// <summary>
        /// The dispatcher timer used for invoking persistence
        /// </summary>
        private DispatcherTimer PersistenceTimer
        {
            get
            {
                return _persistenceTimer;
            }
            set
            {
                _persistenceTimer = value;
                NotifyOfPropertyChange(() => PersistenceTimer);
            }
        }

        #endregion Private Properties

        #region Methods

        /// <summary>
        /// Shows the downloads view
        /// </summary>
        public void ShowDownloads()
        {
            ActivateItem(ProfileViewModel);
        }

        /// <summary>
        /// Shows the bandwidth providers view
        /// </summary>
        public void ShowBandwidthProviders()
        {
            ActivateItem(BandwidthProvidersViewModel);
        }

        /// <summary>
        /// Show/Hide the settings menu
        /// </summary>
        public void ToggleSettingsMenu()
        {
            IsSettingsVisible = !IsSettingsVisible;
        }

        /// <summary>
        /// Show plugin settings
        /// </summary>
        /// <param name="plugin">The plugin who's settings to show.</param>
        public void ShowPluginSettings(IDownloadPlugin plugin)
        {
            //
            // Get download UI service
            //
            IDownloadUIService downloadUIService;
            if (!ImportService.TryGetExportValue(DownloadPluginContractNameService.CreateDownloadUIServiceContractName(plugin.GUID), out downloadUIService))
            {
                MessageDialogViewModel.ShowError("Couldn't load the UI Service from the " + plugin.DisplayName + " plugin.");
                return;
            }

            //
            // Show the settings for the passed plugin
            //
            ToggleSettingsMenu();
            downloadUIService.ShowSettings();
        }

        #endregion Methods

        #region Private Methods

        private void SetupPersistenceTimer()
        {
            PersistenceTimer = new DispatcherTimer();
            PersistenceTimer.Interval = new TimeSpan(0, 0, 0, 5);
            PersistenceTimer.Tick += PersistenceTimerOnTick;
            PersistenceTimer.Start();
        }

        #endregion Private Methods

        #region Event Handlers

        private void PersistenceTimerOnTick(object sender, EventArgs eventArgs)
        {
            if (ProfilePersistenceService == null) return;
            ProfilePersistenceService.Save();
        }

        #endregion Event Handlers
    }
}
